#include"vgrid.h"
#include<stdlib.h>
#include<math.h>
#include<stdio.h>
#include"glheader.h"

void VGrid::Init (int n, bool bind_top, bool bind_side)
{
  printf("Init\n");
  this->n = n;
  tex=false;
  n_vertices = n*n;
  SetVertArray((float *) malloc(sizeof(float) * n_vertices * 3));
  SetNormalArray((float *) malloc(sizeof(float) * n_vertices * 3));
  n_triangles = 2*(n-1)*(n-1);
  triangles = (unsigned int *) malloc(sizeof(unsigned int) * n_triangles * 3);
  //printf("VGrid %d %d\n", n_vertices,n_triangles);
  //indices do grid
  int t = 0;
  int i_lim = bind_top?n-2:n-1;
  int j_lim = bind_side?n-2:n-1;
  for(int i=0;i<i_lim;i++){
    for(int j=0;j<j_lim;j++){
      int v1 = i*n+j;
      int v2 = v1+1;
      int v3 = v1+n;
      int v4 = v3+1;
      int t1 = t*6;
      Set2Triangles(t*6,v1,v2,v3,v4);
      t++;
    }
  }
  if(bind_top){
    int i = n-2;
    //for(int j=0;j<j_lim;j++){
    for(int j=0;j<n-1;j++){
      int v1 = i*n+j;
      int v2 = v1+1;
      int v3 = j;
      int v4 = v3+1;
      Set2Triangles(t*6,v1,v2,v3,v4);
      t++;
    }
  }
  if(bind_side){
    int j = n-2;
    for(int i=0;i<i_lim;i++){
      int v1 = i*n+j;
      int v2 = v1-(n-2);
      int v3 = v1+n;
      int v4 = v3-(n-2);
      Set2Triangles(t*6,v1,v2,v3,v4);
      t++;
    }
  }
  //if(bind_side && bind_top)
    //n_triangles-=2;
}

void VGrid::Set2Triangles(int t1,int v1,int v2,int v3,int v4){
  int t2 = t1+3;
  triangles[t1]   = v1;
  triangles[t1+1] = v3;
  triangles[t1+2] = v4;
  triangles[t2]   = v1;      
  triangles[t2+1] = v4;      
  triangles[t2+2] = v2;
}

void VGrid::CalcNormals ()
{
  printf("CalcNormals\n");
  float * v_normals = GetNormalArray();
  float * vertices = GetVertArray();
  for(int i=0;i<n_vertices;i++){
    v_normals[i*3]   = 0;
    v_normals[i*3+1] = 0;
    v_normals[i*3+2] = 0;
  }
  for(int id=0;id<n_triangles;id++){
    float d1[3];
    float d2[3];
    float t_normal[3];
    for(int j=0; j<3; j++){
      d1[j] = vertices[triangles[id*3]*3+j] - vertices[triangles[id*3+1]*3+j];
      d2[j] = vertices[triangles[id*3+1]*3+j] - vertices[triangles[id*3+2]*3+j];
    }
    //calculando a normal do triangulo
    vs_normcrossprod(d1, d2, t_normal);
    //atualizando noraml x dos vertices do triangulo
    v_normals[triangles[id*3]*3]     += t_normal[0];
    v_normals[triangles[id*3+1]*3]   += t_normal[0];
    v_normals[triangles[id*3+2]*3]   += t_normal[0];
    //atualizando noraml y dos vertices do triangulo
    v_normals[triangles[id*3]*3+1]   += t_normal[1];
    v_normals[triangles[id*3+1]*3+1] += t_normal[1];
    v_normals[triangles[id*3+2]*3+1] += t_normal[1];
    //atualizando noraml z dos vertices do triang
    v_normals[triangles[id*3]*3+2]   += t_normal[2];
    v_normals[triangles[id*3+1]*3+2] += t_normal[2];
    v_normals[triangles[id*3+2]*3+2] += t_normal[2];
  }
  for(int id = 0; id<n_vertices; id++){
    vs_normalize(&v_normals[id*3]);
  }
}

void VGrid::InvertNormals ()
{
  float * v_normals = GetNormalArray();
  for(int i=0;i<n;i++){
    v_normals[i*3]*=-1;
    v_normals[i*3+1]*=-1;
    v_normals[i*3+2]*=-1;
  }
}

void VGrid::FillCoordAndBox()
{
  //printf("VGrid::FillCoordAndBox\n");
  float * vertices = GetVertArray();
  for(int i=0;i<n;i++){
    for(int j=0;j<n;j++){
      int v = (i*n+j)*3;
      vertices[v]   = (float)j/(float)(n-1)-0.5;
      vertices[v+1] = (float)i/(float)(n-1)-0.5;
      vertices[v+2] = 0.0;
      //printf("%d %f %f %f\n",i*n+j,vertices[v],vertices[v+1],vertices[v+2]);
    }
  }
  xmax=1.0;
  ymax=1.0;
  zmax=1.0;
  xmin=-1.0;
  ymin=-1.0;
  zmin=-1.0;
}

void VGrid::SetupTex (int id)
{
  SetupTex(id,1.0,1.0);
}

void VGrid::SetupTex (int id, float rep)
{
  SetupTex(id,rep,rep);
}

void VGrid::SetupTex (int id,float rept, float reps)
{
  float * tex_coord = (float *) malloc(sizeof(float) * n_vertices * 2);
  float step_s = reps/(n-1);
  float step_t = rept/(n-1);
  for(int s=0;s<n;s++){
    for(int t=0;t<n;t++){
      int i = (s*n+t)*2;
      //tex_coord[i] = s*step;
      //tex_coord[i+1] = t*step;
      tex_coord[i] = t*step_t;
      tex_coord[i+1] = s*step_s;
      //printf("texfill s=%d, t=%d, s*step=%f, t*step=%f\n",s,t,s*step,t*step);
    }
  }
  AddVertAttrib(id,2,GL_FLOAT, GL_FALSE, 0, tex_coord);
}

void VGrid::CalcTangentVec (int id,bool bind_side)
{
  printf("CalcTangentVec %d %s\n",id, bind_side?"true":"false");
  float * vertices = GetVertArray();
  float * tang = (float *) malloc(sizeof(float) * n_vertices * 3); 
  for(int i=0;i<n;i++){
    for(int j=0;j<n;j++){
      float * v_prev, *v_next;
      int id = (i*n+j)*3;
      if(j==0){
        if(bind_side)
          v_prev = &vertices[(i*n+n-1)*3];
        else
          v_prev = &vertices[id];
      }
      else
        v_prev = &vertices[id-3];
      if(j==n-1){
        if(bind_side)
          v_next = &vertices[(j*n)*3];
        else
          v_next = &vertices[id];
      }
      else
        v_next = &vertices[id+3];
      tang[id] = v_next[0]-v_prev[0];
      tang[id+1] = v_next[1]-v_prev[1];
      tang[id+2] = v_next[2]-v_prev[2];
      //if(i==0){
        //printf("%d x=%f y=%f z=%f\n",j,tang[id],tang[id+1],tang[id+2]);
      //}
    }
  }
  AddVertAttrib(id,3,GL_FLOAT, GL_FALSE, 0, tang);
}

